package br.com.rookgraph.heuristica;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;

import br.com.rookgraph.Edge;
import br.com.rookgraph.Swap;

public class Plus2 implements Heuristica {

	private int quantidadeTrocas = 0;
	private int swapBetaDecidiu = 0;
	private int swapGamaDecidiu = 0;
	private int swapSigmaDecidiu = 0;
	private int swapSigmaLinhaDecidiu = 0;

	public boolean consideraArticulacoes;
	
	public Plus2() {
		this.consideraArticulacoes = false;
	}
	
	public Plus2(boolean realizaPreProcessamento) {
		this.consideraArticulacoes = realizaPreProcessamento;
	}
	
	/**
	 * Compara as duas trocas (this e other), e 
	 * retorna a melhor entre as duas.
	 *   
	 * @param candidata
	 * @param graph 
	 * @return
	 */
     // Não Considera articulações 
	public Swap getMelhorTroca(Swap best, Swap candidata) {
		if (best == null && candidata != null) {
			return candidata;
		} else {
			int swapBetaCandidata = candidata.swapBeta();
			int swapBetaBest = best.swapBeta();
			
			if (swapBetaCandidata < swapBetaBest) {
				// Swap Beta é decisivo na comparação entre a candidata e a melhor.
				this.swapBetaDecidiu++;
				this.quantidadeTrocas++;
				return candidata;
			} else {
				if (swapBetaCandidata == swapBetaBest) {
					int swapGamaCandidata = candidata.swapGama();
					int swapGamaBest = best.swapGama();
					
					if (swapGamaCandidata < swapGamaBest) {
						// Swap Gama é decisivo na comparação entre a candidata e a melhor.
						this.quantidadeTrocas++;
						this.swapGamaDecidiu++;
						return candidata;
												
					} else if (swapGamaCandidata == swapGamaBest) {
						int swapSigmaCandidata = candidata.swapSigma();
						int swapSigmaBest = best.swapSigma();
						
						if (swapSigmaCandidata < swapSigmaBest) {
							// Swap Sigma é decisivo na comparação entre a candidata e a melhor.
							this.quantidadeTrocas++;
							this.swapSigmaDecidiu++;
							return candidata;
							
						} else if (swapSigmaCandidata == swapSigmaBest) {
							int swapSigmaLinhaCandidata = candidata.swapSigmaLinha();
							int swapSigmaLinhaBest = best.swapSigmaLinha();
							
							if (swapSigmaLinhaCandidata < swapSigmaLinhaBest) {
								// Swap Sigma Linha é decisivo na comparação entre a candidata e a melhor.
								this.quantidadeTrocas++;
								this.swapSigmaLinhaDecidiu++;
								return candidata;
							}
						}
					}
				}
			}
		}
		
		return best;
	}

    // considera articulacoes 
	public Swap getMelhorTroca2(Swap best, Swap candidata) {
		if (best == null && candidata != null) {
			return candidata;
		} else {
			int swapBetaCandidata = candidata.swapBeta();
			int swapBetaBest = best.swapBeta();
			
			if (swapBetaCandidata < swapBetaBest) {
				// Swap Beta é decisivo na comparação entre a candidata e a melhor.
				this.swapBetaDecidiu++;
				this.quantidadeTrocas++;
				return candidata;
			} else {
				if (swapBetaCandidata == swapBetaBest) {
					int swapGamaCandidata = candidata.swapGama();
					int swapGamaBest = best.swapGama();
					
					if (swapGamaCandidata < swapGamaBest) {
						// Swap Gama é decisivo na comparação entre a candidata e a melhor.
						this.quantidadeTrocas++;
						this.swapGamaDecidiu++;
						return candidata;
												
					} else if (swapGamaCandidata == swapGamaBest) {
						int swapSigmaCandidata = candidata.swapSigma();
						int swapSigmaBest = best.swapSigma();
						
						if (swapSigmaCandidata < swapSigmaBest) {
							// Swap Sigma é decisivo na comparação entre a candidata e a melhor.
							this.quantidadeTrocas++;
							this.swapSigmaDecidiu++;
							return candidata;
							
						} else if (swapSigmaCandidata == swapSigmaBest) {
							int swapSigmaLinhaCandidata = candidata.swapSigmaLinha();
							int swapSigmaLinhaBest = best.swapSigmaLinha();
							
							if (swapSigmaLinhaCandidata  < swapSigmaLinhaBest) {
								// Swap Sigma Linha é decisivo na comparação entre a candidata e a melhor.
								this.quantidadeTrocas++;
								this.swapSigmaLinhaDecidiu++;
								return candidata;
							}
						}
					}
				}
			}
		}
		
		return best;
	}



	@Override
	public Edge selectForCut(Edge candidate, Edge edgeCut) {
		return null;
	}

	@Override
	public Edge selectForRep(Edge candidate, Edge edgeRep) {
		return null;
 	}

	/* (non-Javadoc)
	 * @see br.com.rookgraph.heuristica.Heuristica#isVantajoso(br.com.rookgraph.Edge, br.com.rookgraph.Edge)
	 *
	 * Esse metodo pode ser melhorado chamando um dos acima
	 * -TODO verifica isso
	 *
	 */
	@Override
	public boolean isVantajoso(Edge edgeRep, Edge edgeCut) {
		return false;
	}

	public void imprimeDecisoes(int numG) {
		System.out.println("Swap Beta:\t" + swapBetaDecidiu);
		System.out.println("Swap Gama:\t" + swapGamaDecidiu);
		System.out.println("Swap Sigma:\t" + swapSigmaDecidiu);
		System.out.println("Swap SigmaL:\t" + swapSigmaLinhaDecidiu);
		System.out.println("Trocas:\t\t" + quantidadeTrocas);
	}
	
	public void gravaDecisoes(int numG, int grafo, int numV, int incEdge) {
		try {
			String nameFile = numG + "Grafos.csv";
			File file = new File("resources/graph-result-count/" + nameFile);
			
			FileWriter fw = new FileWriter(file, true);
			BufferedWriter out = new BufferedWriter(fw);
			
			StringBuilder sb = new StringBuilder();
			sb.append("Graph " + grafo + ";");
			sb.append(numV + ";");
			sb.append(incEdge + ";");
			sb.append(this.swapBetaDecidiu + ";");
			sb.append(this.swapGamaDecidiu + ";");
			sb.append(this.swapSigmaDecidiu + ";");
			sb.append(this.swapSigmaLinhaDecidiu + ";");
			
			out.write(sb.toString());
			out.newLine();
						
			out.close();
			fw.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	@Override
	public boolean considerarArticulacoes() {
		return this.consideraArticulacoes;
	}
	
}